package com.googlecode.archimedes.filegen.template;

import java.text.MessageFormat;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * The Template class encapsulates the details around a template. It is used by the underlying generation functions to determine what engine-specific
 * templates to execute.
 * 
 * @author John Lema, Erik Gustavson
 * @version $Id: Template.java 2820 2006-08-22 18:44:06 +0000 (Tue, 22 Aug 2006) erik $
 */
public class Template {

	private Log					logger				= LogFactory.getLog(this.getClass().getName());

	private String				extension			= "";											// .java, .do, .jsp, .whatever
	private String				templateName		= "";											// the "Action" in "Action.vm" and
	// CustomerAction.java
	private String				outputPath			= "";											// relative /yomomma/web-inf/foo/etc "
	private Class				allowedAssetType	= null;										// what kind of Asset this template operates on.
	private String				fileName			= "{0}";
	private String				format				= CAPFIRST;
	private boolean				abstractAllowed		= false;
	private boolean				overwriteAllowed	= true;
	private boolean				flat				= false;

	public static final String	UPPER				= "upper";
	public static final String	LOWER				= "lower";
	public static final String	CAMEL				= "camel";
	public static final String	CAPFIRST			= "capfirst";

	public Template() {
		super();
	}

	/**
	 * @return where do you want the file to go? "c://Windows//yomomma//"?
	 */
	public String getOutputPath() {
		return outputPath;
	}

	/**
	 * @param outputPath
	 *            where do you want the file to go? "c://Windows//yomomma//"?
	 */
	public void setOutputPath(String outputPath) {
		this.outputPath = outputPath;
	}

	/**
	 * @return .java, .do, .jsp, .whatever
	 */
	public String getExtension() {
		return extension;
	}

	/**
	 * @param extension
	 *            .java, .do, .jsp, .whatever
	 */
	public void setExtension(String extension) {
		this.extension = extension;
	}

	/**
	 * @return the "Action" in "Action.vm" and CustomerAction.java
	 */
	public String getTemplateName() {
		return templateName;
	}

	/**
	 * @param extension
	 *            the "Action" in "Action.vm" and CustomerAction.java
	 */
	public void setTemplateName(String templateName) {
		this.templateName = templateName;
	}

	/**
	 * Output the TemplateFile as a string
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("TemplatePath [" + this.getOutputPath() + "] ");
		sb.append("TemplateName [" + this.getTemplateName() + "] ");
		sb.append("Extension [" + this.getExtension() + "] ");
		sb.append("Type [" + this.getAllowedAsset() + "] ");
		return sb.toString();
	}

	/**
	 * Used by the templating system to determine which asset types this template is applied to.
	 * 
	 * @return a Class representing the allowed Asset type
	 */
	public Class getAllowedAssetClass() {
		return allowedAssetType;
	}

	/**
	 * Used by the templating system to determine which asset types this template is applied to.
	 * 
	 * @param allowedAssetType
	 *            The Class of the Asset this template operates on
	 */
	public void setAllowedAssetClass(Class allowedAssetType) {
		this.allowedAssetType = allowedAssetType;
	}

	/**
	 * Used by the templating system to determine which asset types this template is applied to.
	 * 
	 * @param allowedAssetType
	 *            A String representing the fully-qualified classname of the Asset this template operates on
	 */
	public void setAllowedAsset(String allowedAssetType) throws ClassNotFoundException {
		Class assetType = Class.forName(allowedAssetType);
		this.allowedAssetType = assetType;
	}

	public String getAllowedAsset() {
		return this.allowedAssetType != null ? allowedAssetType.getName() : "[undefined]";
	}

	/**
	 * Returns the capitalization.
	 * 
	 * @return String value of capitalization
	 */
	public String getFormat() {
		return format;
	}

	/**
	 * Sets the capitalization
	 * 
	 * @param capitalization
	 *            The capitalization to set.
	 */
	public void setFormat(String format) {
		this.format = format;
	}

	/**
	 * Returns the fileName.
	 * 
	 * @return String value of fileName
	 */
	public String getFileName() {
		return fileName;
	}

	/**
	 * Sets the fileName
	 * 
	 * @param fileName
	 *            The fileName to set.
	 */
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	/**
	 * Returns the abstractAllowed.
	 * 
	 * @return boolean value of abstractAllowed
	 */
	public boolean isAbstractAllowed() {
		return abstractAllowed;
	}

	/**
	 * Sets the abstractAllowed
	 * 
	 * @param abstractAllowed
	 *            The abstractAllowed to set.
	 */
	public void setAbstractAllowed(boolean abstractAllowed) {
		this.abstractAllowed = abstractAllowed;
	}

	/**
	 * Returns a properly formated filename
	 * 
	 * @param args
	 * @return
	 */
	public String resolveFileName(Object[] args) {
		String result = MessageFormat.format(getFileName(), args);

		if (this.getFormat().equals(CAPFIRST)) {
			result = result.substring(0, 1).toUpperCase() + result.substring(1);
		} else if (this.getFormat().equals(UPPER)) {
			result = result.toUpperCase();
		} else if (this.getFormat().equals(LOWER)) {
			result = result.toLowerCase();
		} else if (this.getFormat().equals(CAMEL)) {
			result = result.substring(0, 1).toLowerCase() + result.substring(1);
		}

		return result;
	}

	/**
	 * @param overwriteAllowed
	 *            the overwriteAllowed to set
	 */
	public void setOverwriteAllowed(boolean overwriteAllowed) {
		this.overwriteAllowed = overwriteAllowed;
	}

	/**
	 * @return the overwriteAllowed
	 */
	public boolean isOverwriteAllowed() {
		return overwriteAllowed;
	}

	/**
	 * @param flat
	 *            the flat to set
	 */
	public void setFlat(boolean flat) {
		this.flat = flat;
	}

	/**
	 * @return the flat
	 */
	public boolean isFlat() {
		return flat;
	}
}